#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <strings.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <nlohmann/json.hpp>
#include "../../include/Reactor/ProtocolParser.h"

using namespace std;

int readn(int fd, char *buf, int len) 
{
    int left = len; 
    char *pstr = buf; //读缓存区的首地址
    int ret = 0;

    while(left > 0)
    {
        ret = ::recv(fd, pstr, left, 0);
        //对当前进程（线程）而言发生了中断
        //中断触发，导致CPU的使用权被抢夺，后续应该继续执行
        if(-1 == ret && errno == EINTR)
        {
            continue;
        }
        else if(-1 == ret)
        {
            perror("read error -1");
            return -1;
        }
        else if(0 == ret)
        {
            break;
        }
        else
        {
            pstr += ret; 
            left -= ret; 
        }
    }

    return len - left;
}

int tcp_connect(const char* host, const char* service)
{
    int sockfd = socket(AF_INET, SOL_SOCKET, 0);

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(service));
    addr.sin_addr.s_addr = inet_addr(host);

    connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));
    
    return sockfd;
}

void send_message(int connfd, const Message& msg)
{
#ifdef DEBUG
    cout << "msg.tag: " << msg.tag << endl;
    cout << "msg.value: " << msg.value << endl;
#endif
    string data = ProtocolParser::serializeMessage(msg);
    send(connfd, data.c_str(), data.size(), 0);
}

string recv_message(int connfd)
{
    char header[8] = {0};
    int ret = readn(connfd, header, sizeof(header));
    if(ret != 8)
    {
        return ""; // 返回空字符串代表连接出错或读取失败
    }

    int32_t tag = 0;
    int32_t length = 0;
    memcpy(&tag, header, sizeof(tag));
    memcpy(&length, header + 4, sizeof(length));
    int32_t realLength = ntohl(length);
#ifdef DEBUG
    cout << "tag: " << ntohl(tag) << endl;
    cout << "length: " << realLength << endl;
#endif

    string data;
    data.resize(8 + realLength);
    memcpy(data.data(), header, 8);
    ret = readn(connfd, data.data() + 8, realLength);
    if(ret != realLength)
    {
        return "";
    }

    return data;
}

int main()
{
    const char* host = "127.0.0.1";
    const char* service = "8888";
    int connfd = tcp_connect(host, service); 
    if (connfd == -1) {
        std::cerr << "Error: connnect server failed!\n";
        exit(1);
    }

    for (;;) {
        cout << "请输入: <Tag><Value>\n";
        Message message;
        if(std::cin >> message.tag >> message.value)
        {
            // std::cin >> message.value;
            message.length = message.value.size();

            send_message(connfd, message);

            string data = recv_message(connfd);
            Message msg = ProtocolParser::parseMessage(data);

            cout << msg.value << endl;
            cout << "#########################################################" << endl;
        }else
        {
            cout << "请输入：<Tag> 1 (关键词推荐), 2 (网页搜索) <Value>" << endl;
            cin.clear();
            cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        }

    }
}